<!--
  - @copyright Copyright (c) 2019 Georg Ehrke <oc.list@georgehrke.com>
  -
  - @author Georg Ehrke <oc.list@georgehrke.com>
  -
  - @license GNU AGPL version 3 or any later version
  -
  - This program is free software: you can redistribute it and/or modify
  - it under the terms of the GNU Affero General Public License as
  - published by the Free Software Foundation, either version 3 of the
  - License, or (at your option) any later version.
  -
  - This program is distributed in the hope that it will be useful,
  - but WITHOUT ANY WARRANTY; without even the implied warranty of
  - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  - GNU Affero General Public License for more details.
  -
  - You should have received a copy of the GNU Affero General Public License
  - along with this program. If not, see <http://www.gnu.org/licenses/>.
  -
  -->

<template>
	<div>
		<InviteesListSearch
			v-if="!isReadOnly && hasUserEmailAddress"
			:already-invited-emails="alreadyInvitedEmails"
			@addAttendee="addAttendee" />
		<OrganizerListItem
			v-if="hasOrganizer"
			:is-read-only="isReadOnly"
			:organizer="calendarObjectInstance.organizer" />
		<InviteesListItem
			v-for="invitee in inviteesWithoutOrganizer"
			:key="invitee.email"
			:attendee="invitee"
			:is-read-only="isReadOnly"
			:organizer-display-name="organizerDisplayName"
			@removeAttendee="removeAttendee" />
		<NoInviteesView
			v-if="isReadOnly && isListEmpty" />
		<NoInviteesView
			v-if="!isReadOnly && isListEmpty && hasUserEmailAddress" />
		<OrganizerNoEmailError
			v-if="!isReadOnly && isListEmpty && !hasUserEmailAddress" />

		<div class="invitees-list-button-group">
			<button
				v-if="isCreateTalkRoomButtonVisible"
				:disabled="isCreateTalkRoomButtonDisabled"
				@click="createTalkRoom">
				{{ $t('calendar', 'Create Talk room for this event') }}
			</button>

			<button v-if="!isReadOnly" :disabled="isListEmpty" @click="openFreeBusy">
				{{ $t('calendar', 'Show busy times') }}
			</button>
			<FreeBusy
				v-if="showFreeBusyModel"
				:attendees="calendarObjectInstance.attendees"
				:organizer="calendarObjectInstance.organizer"
				:start-date="calendarObjectInstance.startDate"
				:end-date="calendarObjectInstance.endDate"
				@close="closeFreeBusy" />
		</div>
	</div>
</template>

<script>
import { mapState } from 'vuex'
import InviteesListSearch from './InviteesListSearch'
import InviteesListItem from './InviteesListItem'
import OrganizerListItem from './OrganizerListItem'
import NoInviteesView from './NoInviteesView.vue'
import OrganizerNoEmailError from './OrganizerNoEmailError.vue'
import { createTalkRoom, doesDescriptionContainTalkLink } from '../../../services/talkService.js'
import FreeBusy from '../FreeBusy/FreeBusy.vue'
import {
	showSuccess,
	showError,
} from '@nextcloud/dialogs'

export default {
	name: 'InviteesList',
	components: {
		FreeBusy,
		OrganizerNoEmailError,
		NoInviteesView,
		InviteesListItem,
		InviteesListSearch,
		OrganizerListItem,
	},
	props: {
		isReadOnly: {
			type: Boolean,
			required: true,
		},
		calendarObjectInstance: {
			type: Object,
			required: true,
		},
	},
	data() {
		return {
			creatingTalkRoom: false,
			showFreeBusyModel: false,
		}
	},
	computed: {
		...mapState({
			talkEnabled: state => state.settings.talkEnabled,
		}),
		inviteesWithoutOrganizer() {
			if (!this.calendarObjectInstance.organizer) {
				return this.calendarObjectInstance.attendees
			}

			return this.calendarObjectInstance.attendees
				.filter(attendee => attendee.uri !== this.calendarObjectInstance.organizer.uri)
		},
		hasOrganizer() {
			return this.calendarObjectInstance.organizer !== null
		},
		organizerDisplayName() {
			if (!this.calendarObjectInstance.organizer) {
				return ''
			}

			if (this.calendarObjectInstance.organizer.commonName) {
				return this.calendarObjectInstance.organizer.commonName
			}

			if (this.calendarObjectInstance.organizer.uri.startsWith('mailto:')) {
				return this.calendarObjectInstance.organizer.uri.substr(7)
			}

			return this.calendarObjectInstance.organizer.uri
		},
		isListEmpty() {
			return this.calendarObjectInstance.organizer === null
				&& this.calendarObjectInstance.attendees.length === 0
		},
		alreadyInvitedEmails() {
			const emails = this.calendarObjectInstance.attendees.map(attendee => {
				if (attendee.uri.startsWith('mailto:')) {
					return attendee.uri.substr(7)
				}

				return attendee.uri
			})

			const principal = this.$store.getters.getCurrentUserPrincipal
			if (principal) {
				emails.push(principal.emailAddress)
			}

			return emails
		},
		hasUserEmailAddress() {
			const principal = this.$store.getters.getCurrentUserPrincipal
			if (!principal) {
				return false
			}

			return !!principal.emailAddress
		},
		isCreateTalkRoomButtonVisible() {
			return this.talkEnabled
		},
		isCreateTalkRoomButtonDisabled() {
			if (this.creatingTalkRoom) {
				return true
			}

			if (doesDescriptionContainTalkLink(this.calendarObjectInstance.description)) {
				return true
			}

			return false
		},
	},
	methods: {
		addAttendee({ commonName, email, calendarUserType, language, timezoneId }) {
			this.$store.commit('addAttendee', {
				calendarObjectInstance: this.calendarObjectInstance,
				commonName,
				uri: email,
				calendarUserType,
				participationStatus: 'NEEDS-ACTION',
				role: 'REQ-PARTICIPANT',
				rsvp: true,
				language,
				timezoneId,
			})

			if (!this.hasOrganizer) {
				const principal = this.$store.getters.getCurrentUserPrincipal
				if (!principal) {
					return
				}

				this.$store.commit('setOrganizer', {
					calendarObjectInstance: this.calendarObjectInstance,
					commonName: principal.displayname,
					email: principal.emailAddress,
				})
			}
		},
		removeAttendee(attendee) {
			this.$store.commit('removeAttendee', {
				calendarObjectInstance: this.calendarObjectInstance,
				attendee,
			})
		},
		openFreeBusy() {
			this.showFreeBusyModel = true
		},
		closeFreeBusy() {
			this.showFreeBusyModel = false
		},
		async createTalkRoom() {
			const NEW_LINE = '\r\n'
			try {
				this.creatingTalkRoom = true
				const url = await createTalkRoom(this.calendarObjectInstance.title)

				let newDescription
				if (!this.calendarObjectInstance.description) {
					newDescription = url + NEW_LINE
				} else {
					newDescription = this.calendarObjectInstance.description + NEW_LINE + NEW_LINE + url + NEW_LINE
				}

				this.$store.commit('changeDescription', {
					calendarObjectInstance: this.calendarObjectInstance,
					description: newDescription,
				})

				showSuccess(this.$t('calendar', 'Successfully appended link to talk room to description.'))
			} catch (error) {
				showError(this.$t('calendar', 'Error creating Talk room'))
			} finally {
				this.creatingTalkRoom = false
			}
		},
	},
}
</script>
